﻿
namespace TFSChangeLog.Operations.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Threading;
    using System.Xml;
    using TFSChangeLog.GeneralUtilities;
    using TFSChangeLog.ViewModel;

    /// <summary>Summary description for <see cref="GenerateReleaseNotesService"/> class.</summary>
    public static class GenerateReleaseNotesService
    {
        /// <summary>Summary description for <c>GenerateReleaseNotesService</c> method.</summary>
        /// <param name="singleIterationList">TODO: Summary description for <c>singleIterationList</c> parameter of type <c>int[]</c>.</param>
        /// <param name="m_ViewModel">TODO: Summary description for <c>m_ViewModel</c> parameter of type <c>TFSChangeLog.ViewModel.MainWindowViewModel</c>.</param>
        public static void DoWork(int[] singleIterationList, MainWindowViewModel m_ViewModel)
        {
            var loopOptions = new ParallelOptions();
            loopOptions.CancellationToken = m_ViewModel.progressDialogViewModel.TokenSource.Token;
            try
            {
                Parallel.ForEach(singleIterationList, loopOptions, t => GenerateRelaseNotes(m_ViewModel));
            }
            catch (OperationCanceledException)
            {
                var ShowCancellationMessage = new Action(m_ViewModel.progressDialogViewModel.ShowCancellationMessage);
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, ShowCancellationMessage);
            }
            catch (Exception e)
            {
                var ShowCancellationMessage = new Action(m_ViewModel.progressDialogViewModel.ShowCancellationMessage);
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, ShowCancellationMessage);
            }
        }

        /// <summary>Summary description for <c>GenerateReleaseNotesService</c> method.</summary>
        /// <param name="m_ViewModel">TODO: Summary description for <c>m_ViewModel</c> parameter of type <c>TFSChangeLog.ViewModel.MainWindowViewModel</c>.</param>
        public static void GenerateRelaseNotes(MainWindowViewModel m_ViewModel)
        {
            ProgressDialogViewModel viewModel = m_ViewModel.progressDialogViewModel;
            TFSChangeLog.DataAccess.TFSChangeLogStaticConfigs.ResetDateTimeOnOutputFileNames();
            if (TFSChangeLog.DataAccess.TFSChangeLogStaticConfigs.IsRunningFromCommandPrompt == false)
                {
                SetProgressBarMessage(viewModel);
                }

            if (m_ViewModel.SelectedFromChangeSet.FromChangesetID > m_ViewModel.SelectedToChangeSet.ToChangesetID)
            {
                Console.WriteLine(
                                         "ERROR                  : Selected Value in 'Start From ChangeSet' ({0}) should be less then " +
                                         "'End To ChangeSet' ({1}).",
                                         m_ViewModel.SelectedFromChangeSet.FromChangesetID,
                                         m_ViewModel.SelectedToChangeSet.ToChangesetID);

// m_ViewModel.RaiseChangeSetSelectionError();
            }
            else
            {
                var changeSetENum = from FromChangeSetViewModel in m_ViewModel.FromChangeSets
                                    where (FromChangeSetViewModel.FromChangesetID >= m_ViewModel.SelectedFromChangeSet.FromChangesetID
                                    && FromChangeSetViewModel.FromChangesetID <= m_ViewModel.SelectedToChangeSet.ToChangesetID)
                                    select FromChangeSetViewModel;

                var settings = new XmlWriterSettings();
                settings.CheckCharacters = true;
                settings.Encoding = Encoding.UTF8;
                settings.Indent = true;
                settings.IndentChars = "  ";
                settings.NewLineChars = "\n";
                settings.NewLineHandling = NewLineHandling.Replace;

                using (XmlWriter writer = XmlWriter.Create(DataAccess.TFSChangeLogStaticConfigs.TFSChangeLogXMLFileName, settings))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("ChangeLog");
                    writer.WriteElementString("TFSServer", m_ViewModel.TFSServerName);
                    writer.WriteElementString("TFSProjectName", m_ViewModel.TFSProjectName);
                    writer.WriteElementString("TFSProjectBranchName", m_ViewModel.TFSProjectSelectedBranchName);
                    writer.WriteElementString("ReportDate", DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString());
                    writer.WriteElementString("ReportProducedBy", m_ViewModel._currentUser.DisplayName);
                    writer.WriteElementString("FromChangeSet", m_ViewModel.SelectedFromChangeSet.FromChangesetID.ToString());
                    writer.WriteElementString("ToChangeSet", m_ViewModel.SelectedToChangeSet.ToChangesetID.ToString());

                    writer.WriteStartElement("ChangeSets");
                    foreach (var changeSetInENum in changeSetENum)
                    {
                        writer.WriteStartElement("ChangeSet");
                        writer.WriteElementString("ID", changeSetInENum.FromChangeSet.ChangesetId.ToString());
                        writer.WriteElementString("Date", changeSetInENum.FromChangeSet.CreationDate.ToString());
                        writer.WriteElementString("Comment", changeSetInENum.FromChangeSet.Comment);
                        writer.WriteElementString("User", changeSetInENum.FromChangeSet.Committer);

                        if (changeSetInENum.FromChangeSet.WorkItems.Count() > 0)
                        {
                            writer.WriteStartElement("WorkItems");
                            foreach (var workItemInChangeSet in changeSetInENum.FromChangeSet.WorkItems)
                            {
                                if (m_ViewModel.progressDialogViewModel.TokenSource.Token.IsCancellationRequested)
                                    {
                                        return;
                                    }

                                writer.WriteStartElement("WorkItem");
                                foreach (Microsoft.TeamFoundation.WorkItemTracking.Client.FieldDefinition wiField
                                    in workItemInChangeSet.Type.FieldDefinitions)
                                {
                                    try
                                    {
                                        if (workItemInChangeSet[wiField.Name] != null)
                                        {
                                            // TODO: Change following to use Extention methods.
                                            writer.WriteElementString(
                                                                          "_" + wiField.Name.ToString().Replace(" ", string.Empty).
                                                                          Replace("(", string.Empty).Replace(")", string.Empty),
                                                                      workItemInChangeSet[wiField.Name].ToString());
                                        }
                                        else
                                        {
                                            // TODO: Change following to use Extention methods.
                                            writer.WriteElementString(
                                                                          "_" + wiField.Name.ToString().Replace(" ", string.Empty).
                                                                          Replace("(", string.Empty).Replace(")", string.Empty), string.Empty);
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Console.WriteLine("ERROR                  : Exception is : {0}", e.ToString());
                                        continue;
                                    }
                                }

                                writer.WriteEndElement();
                            }

                            writer.WriteEndElement();
                        }
                        else
                        {
                            writer.WriteStartElement("WorkItems");
                            writer.WriteEndElement();
                        }

                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }

                if (TFSChangeLog.DataAccess.TFSChangeLogStaticConfigs.IsIgnoreXSLT == false)
                    {
                    XmlTransformUtil.SaxonTransform(DataAccess.TFSChangeLogStaticConfigs.TFSChangeLogXMLFileName, "ReleaseNotesTemplate.xslt");
                    }

                if (TFSChangeLog.DataAccess.TFSChangeLogStaticConfigs.IsRunningInSilentMode == false)
                    {
                    System.Diagnostics.Process.Start(DataAccess.TFSChangeLogStaticConfigs.TFSChangeLogHTMLFileName);
                    }
            }
        }

        /// <summary>
        /// Set Progress Bar Message.
        /// </summary>
        /// <param name="viewModel">TODO: Summary description for <c>viewModel</c> parameter of type <c>TFSChangeLog.ViewModel.ProgressDialogViewModel</c>.</param>
        private static void SetProgressBarMessage(ProgressDialogViewModel viewModel)
        {
            string message = "Generating Release Notes ...";
            var SetProgressMessage = new Action<string>(viewModel.SetProgressMessage);
            Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, SetProgressMessage, message);
        }
    }
}
